Home > CS2400: Data Structures and Advanced Programming > Stack ADTStack ADT
Stacks:
Name | Description |
---|---|
push | Adds a new entry to the top of the stack |
pop | Removes and returns the stack’s top entry |
peek | Retrieves the stack’s top entry without changing the stack |
isEmpty | Returns whether the stack is empty |
clear | Removes all entries from the stack |
Remember: You can only interact with the item at the top of the stack!
- Don’t implement extra features that go against the specification!
- This means no
toArray
!
public interface StackInterface<T> {
void push(T newEntry);
pop();
T peek();
T boolean isEmpty();
void clear();
}
Case: Stack is empty, what to do with pop
and peak
?
null
Security Note:
Relevancy: “The most important ADT in computer science”
- We wouldn’t have methods or recursion without stacks!
- In this introduction we’ll be using the stack to manipulate algebra.
- The techniques are universal, and used everywhere.
Algebraic Notation:
Note: Why Prefix and Postfix Matter
- In infix, precedence can be ambiguous, which is why parenthesis and the precedence (order of operations) exists.
- So for a computer to evaluate an infix expression, it needs two stacks (variable and operator stack) and it needs to evaluate order of operations.
- In prefix and postfix, precedence is not ambiguous, no parenthesis are needed.
- So prefix and postfix is easier and faster to execute on a computer (you only need to use one stack to evaluate, and you don’t need to worry about order of operations).
# Infix
a + b
# Prefix
+ a b
# Postfix
a b +
# Infix
a + b / c
# Prefix
+ a / b c
# Postfix
a b c / +
Warning: Keep terms on their original sides when converting expressions
- Using the associative rule to switch sides will lose points.
Balanced Expression: An expression with matching brackets and parenthesis.
Q: How do you tell if an infix expression is balanced?
A: Read the expression character-by-character, and:
[
, {
) to the stack as you read it]
, }
) from the stack as you read itQ: How do you programmatically convert an infix expression \to postfix?
A: Read the expression character-by-character and use a stack to store operators:
a
, b
) get appended to the postfix expression as we read them.-
, +
) get pushed into the operator stack as we read them.Remember: The parenthesis themselves don’t get added into postfix notation.
Current Character | Postfix Form | Operator Stack |
---|---|---|
a | a | |
+ | a | + |
b | ab | + |
* | ab | +* |
c | abc | +* |
abc* | + | |
abc*+ |
Current Character | Postfix Form | Operator Stack |
---|---|---|
a | a | |
- | a | - |
b | ab | - |
+ | ab- | + |
c | ab-c | + |
ab-c+ |
Current Character | Postfix Form | Operator Stack |
---|---|---|
a | a | |
^ | a | ^ |
b | ab | ^ |
^ | ab | ^^ |
c | abc | ^^ |
abc ^ | ^ | |
abc ^^ |
^
may appear to have the same precedence as the first ^
—because they’re both the same symbol (so you may want to do ab^c^
)—but the second ^
has a higher precedence because it’s nested in the first one!Current Character | Postfix Form | Operator Stack |
---|---|---|
a | a | |
/ | a | / |
b | ab | / |
* | ab/ | * |
( | ab/ | *( |
c | ab/c | *( |
+ | ab/c | *(+ |
( | ab/c | *(+( |
d | ab/cd | *(+( |
- | ab/cd | *(+(- |
e | ab/cde | *(+(- |
) | ab/cde- | *(+( |
) | ab/cde-+ | *( |
) | ab/cde-+* |
Note: When implementing this in code, make sure that the expression is balanced, or throw an exception when something illegal happens.
Q: How do you programmatically evaluate a postfix expression?
A: We’ll use a stack to evaluate it.
s.push(t)
)op = t
)rhs = s.pop()
)lhs = s.pop()
)s.push(lhs op rhs)
)s.pop()
Stacks make method calling and recursion possible.
public static void main(string[] args) {
int x = 5;
int y = methodA(x);
}
public static int methodA(int a) {
= methodB(a);
a return a;
}
public static int methodB(int b) {
return b;
}
So, by the time methodB()
begins execution, the program activation record looks like this:
methodB
methodA
main
Found in java.util
Methods:
push(T item);
T pop();
T peek();
T boolean empty();
Implementing a stack with a singly linked list is trivial.
head
node as the top of the stack.public final class LinkedStack<T> implements StackInterface {
private Node head;
? /* constructor goes here */
public T peek() {
if (isEmpty()) {
throw new EmptyStackException();
}
return head.data;
}
public T pop() {
T top = peek();
head = head.next;
return top;
}
public T push(T entry) {
Node newEntry = Node(entry);
if (head != null) {
newEntry.next = head;
}
head = newEntry;
}
/* private Node inner-class here */
}
Implementing a stack with an array is best done by using the end of the array as the top of the stack, as it’s the easiest to access.
Vector: Object that behaves like a high-level array.